package org.opens.javaskill.design.apply;

import lombok.Getter;

import java.util.Collections;
import java.util.List;
import java.util.stream.IntStream;

/**
 * 功能:
 * <p>不可变对象的实例</p>
 * @Date 2020/9/8 19:35
 * @Created by 99126
 */
public class ImmutableObjectPattern {

    public static void main(String[] args) {

    }

}

/**
 * 说明:
 * <pre>
 *     1. 不可变对象认为是天然线程安全的, 因为其中的属性只在构造时改变一次, 然后就不再允许这些属性被修改了.
 *     2. jdk官方对于不可变对象的定义:
 *      - 属性都被final和private修饰;
 *      - 类被final修饰;
 *      - 属性没有setter方法;
 *      - 如果一个实例引入了一个不可变对象, 不要允许这个实例改变它.
 *     3. jdk中的String类就是一个不可变对象.
 * </pre>
 */
@Getter
final class ImmutablePerson {

    private final String name;

    private final String address;

    public ImmutablePerson(String name, String address) {
        this.name = name;
        this.address = address;
    }

}

class UseImmutablePersonThread extends Thread {

    private ImmutablePerson immutablePerson;

    public UseImmutablePersonThread(ImmutablePerson immutablePerson) {
        this.immutablePerson = immutablePerson;
    }

    @Override
    public void run() {
        while (true) {
            System.out.println(Thread.currentThread().getName() + " print " + immutablePerson);
        }
    }

    public static void main(String[] args) {
        ImmutablePerson person = new ImmutablePerson("小明", "陕西");
        IntStream.rangeClosed(0, 5).forEach(i -> {
            new UseImmutablePersonThread(person).start();
        });
    }

}

class ImmutableHasObject {

    private final int age;

    private final String name;

    private final List<Integer> idCard;

    public ImmutableHasObject(int age, String name, List<Integer> idCard) {
        this.age = age;
        this.name = name;
        this.idCard = idCard;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }

    public List<Integer> getIdCard() {
        // 由于集合类型有一些方法可以提供修改, 而final知识保证其内存地址不变, 无法保证值不变, 所以在getter中要将这个List转换为不可变的.
        return Collections.unmodifiableList(this.idCard);
    }
}